%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%  Copyright by Wenliang Du.                                       %%
%%  This work is licensed under the Creative Commons                %%
%%  Attribution-NonCommercial-ShareAlike 4.0 International License. %%
%%  To view a copy of this license, visit                           %%
%%  http://creativecommons.org/licenses/by-nc-sa/4.0/.              %%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\newcommand{\commonfolder}{../../common-files}
\input{\commonfolder/header}
\input{\commonfolder/copyright}

\lhead{\bfseries SEED 实验 -- ICMP 重定向攻击实验}
\newcommand{\ipFigs}{./Figs}

\begin{document}

\begin{center}
{\LARGE ICMP 重定向攻击实验}
\end{center}

\seedlabcopyright{2020}

% *******************************************
% SECTION
% ******************************************* 
\section{概述}

ICMP重定向是一种由路由器发送给IP数据包的源端口的错误消息。当路由器认为一个数据包被错误地路由时，它会通知发送者使用不同的路由器来转发后续到同一目的地的数据包。ICMP重定向可以被攻击者用来改变受害者的路由。

本任务的目标是针对受害者发起一个ICMP重定向攻击，使得当受害者向\texttt{192.168.60.5}发送数据包时，它会使用恶意路由器容器（\texttt{10.9.0.111}）作为它的路由器。由于恶意路由器由攻击者控制，攻击者可以拦截这些数据包、对其进行修改，然后重新发送出去。这是一种中间人（MITM）攻击的形式。本实验涵盖了以下部分：

\begin{itemize}[noitemsep]
  \item IP和ICMP协议
  \item ICMP重定向攻击
  \item 路由
\end{itemize}

\paragraph{视频} 关于IP协议及其攻击的详细内容，可以在以下部分找到：

\begin{itemize}
  \item SEED Lecture 第4节，\seedisvideo
\end{itemize}

\paragraph{实验环境} \seedenvironmentC

% *******************************************
% SECTION
% ******************************************* 
\section{使用容器设置环境}

在本实验中，我们需要几台机器。实验环境的搭建如图~\ref{ip:fig:labsetup}所示。我们将使用容器来搭建此环境。

\begin{figure}[htb]
  \begin{center}
    \includegraphics[width=0.8\textwidth]{./Figs/TwoLANs_ICMP.pdf}
  \end{center}
  \caption{实验环境设置}
  \label{ip:fig:labsetup}
\end{figure}

% -------------------------------------------
% SUBSECTION
% -------------------------------------------
\subsection{容器搭建和命令}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\input{\commonfolder/container/setup}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% -------------------------------------------
% SUBSECTION
% -------------------------------------------
\subsection{关于攻击者容器}

在本实验中，我们可以选择使用虚拟机或攻击者容器作为攻击机器。如果查看Docker Compose文件，你会看到攻击者容器的配置与其他容器不同。以下是其中的区别：

\begin{itemize}
  \item \textit{共享文件夹}。当使用攻击者容器发起攻击时，我们需要将攻击代码放入攻击者容器中。
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  \input{\commonfolder/container/volumes}
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

  \item \textit{特权模式}。
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  \input{\commonfolder/container/privileged_mode}
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\end{itemize}

% *******************************************
% SECTION
% ******************************************* 
\section{任务1：发起ICMP重定向攻击}

在Ubuntu操作系统中，有针对ICMP重定向攻击的防范措施。在Compose文件中，我们已经通过配置受害者的容器接受ICMP重定向消息来关闭了这种防范措施。

\begin{lstlisting}
// 在docker-compose.yml
sysctls:
  - net.ipv4.conf.all.accept_redirects=1

// 要开启防护，请将其值设置为0
# sysctl net.ipv4.conf.all.accept_redirects=0
\end{lstlisting}

对于本任务，我们将从攻击者容器对受害者的容器发起攻击。当前的配置中，受害者将使用路由器容器（\texttt{192.168.60.11}）作为通往 \texttt{192.168.60.0/24} 网络的路由器。如果在受害者的容器上运行 \texttt{ip route}，我们将看到以下内容

\begin{lstlisting}
# ip route
default via 10.9.0.1 dev eth0 
10.9.0.0/24 dev eth0 proto kernel scope link src 10.9.0.5 
192.168.60.0/24 via (*@\textbf{10.9.0.11}@*) dev eth0
\end{lstlisting}

\paragraph{代码框架} 提供了一个包含一些必要参数的代码框架，学生们需要在标记为 \texttt{@@@@} 的地方填入正确的值。

\begin{lstlisting}[language=python]
#!/usr/bin/python3

from scapy.all import *

ip = IP(src = @@@@,  dst = @@@@)
icmp = ICMP(type=@@@@, code=@@@@)
icmp.gw = @@@@

# 包裹在IP数据包中的应该是触发重定向消息的那个。
ip2 = IP(src = @@@@, dst = @@@@)
send(ip/icmp/ip2/ICMP());
\end{lstlisting}

\paragraph{验证} ICMP重定向消息不会影响路由表，而是会改变路由缓存。路由缓存中的条目会覆盖路由表中的条目，直到这些条目过期为止。要显示和清理缓存内容，请使用以下命令：

\begin{lstlisting}
// 显示路由缓存
# ip route show cache
192.168.60.5 via 10.9.0.111 dev eth0
    cache <redirected> expires 296sec

// 清理路由缓存
# ip route flush cache
\end{lstlisting}

请在受害者的机器上进行traceroute操作，看看数据包是否被重定向。

\begin{lstlisting}
# mtr -n 192.168.60.5
\end{lstlisting}

\paragraph{注意事项：} 如果我们伪造重定向包，但受害者的机器在攻击期间没有发送过ICMP数据包，则该攻击将永远不成功。这是因为操作系统内核会在接受ICMP重定向消息之前进行一些类型的检查。它会验证该ICMP重定向是否由其自身发出的数据包触发，即它会检查重定向包内的 \texttt{ip2}。这种检查的严格程度取决于操作系统。

对于Ubuntu 20.04，内核只是验证重定向包中的 \texttt{ip2} 是否与触发ICMP重定向的实际数据包的类型和目的IP地址匹配。然而，如果你在苹果硅机器上进行此实验，你的虚拟机版本可能是Ubuntu 22.04或更高版本，并且检查会更加严格。要确保伪造包中的 \texttt{ip2} 能够通过检查，最简单的方法是从受害者的机器中捕获一个数据包。不过这并不是必要的。鼓励学生们使用其他方法进行攻击。

\paragraph{问题} 你在成功发动攻击后，请执行以下实验，并观察你的攻击是否仍然成功。请解释你观察到的现象：

\begin{itemize}
  \item 问题1：你能否使用ICMP重定向攻击将流量重定向到远程机器？即， \texttt{icmp.gw} 赋予的IP地址是一个不在本地局域网上的计算机。请展示实验结果并解释你观察到的现象。

  \item 问题2：你能否使用ICMP重定向攻击将流量重定向到同一网络中的不存在的机器上？即， \texttt{icmp.gw} 赋予的IP地址是一个已断开连接或不存在的本地计算机。请展示实验结果并解释你观察到的现象。

  \item 问题3：查看 \texttt{docker-compose.yml} 文件，你会找到恶意路由器容器的一些条目。这些条目的目的是什么？将它们的值改为1，并再次启动攻击。请描述并解释你观察到的现象。

\begin{lstlisting}
sysctls:
     - net.ipv4.conf.all.send_redirects=0
     - net.ipv4.conf.default.send_redirects=0
     - net.ipv4.conf.eth0.send_redirects=0
\end{lstlisting}
\end{itemize}

% *******************************************
% SECTION
% ******************************************* 
\section{任务2：发起MITM攻击}

通过ICMP重定向攻击，可以使受害者使用我们的恶意路由器（\texttt{10.9.0.111}）作为通往 \texttt{192.168.60.5} 的目标路由。因此，从受害者机器发送到此目的地的所有数据包都将通过恶意路由器进行转发。我们希望能够修改受害者的数据包。

在发起MITM攻击之前，我们在受害者的容器中使用 \texttt{netcat} 启动一个TCP客户端和服务端程序。命令如下：

\begin{lstlisting}
// 在目标容器192.168.60.5上启动netcat服务：
# nc -lp 9090

// 在受害者的容器中连接到服务器：
# nc 192.168.60.5 9090
\end{lstlisting}

一旦建立连接，你可以在受害者机器上输入消息。每行消息都会被放入一个TCP数据包发送至目的地，目的地会简单地显示这些消息。你的任务是将每条消息中的你名字出现的地方替换为一系列A。序列的长度应与你名字相同，否则可能会扰乱TCP序号，从而导致整个TCP连接失败。你需要使用真实的名字，以便我们知道工作是由谁完成的。

\paragraph{禁用IP转发} 在设置中，恶意路由器启用了IP转发功能，因此它像一个路由器一样为其他机器转发数据包。当我们发起MITM攻击时，我们必须停止转发IP数据包；相反，我们将拦截这些数据包、对其进行修改，然后重新发送出去。要做到这一点，我们只需在恶意路由器上禁用IP转发即可。

\begin{lstlisting}
# sysctl net.ipv4.ip_forward=0
\end{lstlisting}

\paragraph{MITM代码} 一旦禁用了IP转发，我们的程序需要从受害者到目标的路径中接管数据包转发角色，并当然在修改数据包后发送它们出去。由于数据包的目的地不是我们自己，内核不会将这个数据包传递给我们；它会简单地丢弃这个数据包。然而，如果我们的程序是一个嗅探器程序，我们将从内核那里获取到这个数据包。因此，我们将使用嗅探和伪造技术来实施这种MITM攻击。以下提供了一个嗅探并伪造的示例程序，用于捕获TCP数据包、对其进行修改后重新发送它们。你可以从实验配置文件中找到代码。

\begin{lstlisting}[language=python, caption={示例代码: \texttt{mitm_sample.py}}]
#!/usr/bin/env python3
from scapy.all import *

def spoof_pkt(pkt):
   newpkt = IP(bytes(pkt[IP]))
   del(newpkt.chksum)
   del(newpkt[TCP].payload)
   del(newpkt[TCP].chksum)

   if pkt[TCP].payload:
       data = pkt[TCP].payload.load
       print("*** %s, length: %d" % (data, len(data)))

       # 替换一个模式
       newdata = data.replace(b'seedlabs', b'AAAAAAAA')

       send(newpkt/newdata)
   else:
       send(newpkt)

f = 'tcp'
pkt = sniff(iface='eth0', filter=f, prn=spoof_pkt)
\end{lstlisting}

请注意，上述代码捕获了所有TCP数据包，包括由程序本身生成的数据包。这是不可取的，因为它会影响性能。学生需要更改过滤器以确保不会捕获到自己的数据包。

\paragraph{问题} 你成功发动攻击后，请回答以下问题：

\begin{itemize}
  \item 问题4：在你的MITM程序中，你需要捕捉一个方向的数据流量。请指出这个方向，并解释为什么。

  \item 问题5：在MITM程序中，当你从A（\texttt{10.9.0.5}）捕获 \texttt{nc} 流量时，你可以使用A的IP地址或MAC地址作为过滤器的一部分。其中有一种选择是不好的，即使这两种选择可能都有效也会引发问题。请尝试两种方法，并通过实验结果展示哪种选择是正确的，并解释你的结论。
\end{itemize}

% *******************************************
% SECTION
% ******************************************* 
\section{提交}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\input{\commonfolder/submission}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\end{document}
